package io.github.frailty9.crserver.controller

import cn.dev33.satoken.annotation.SaCheckRole
import cn.dev33.satoken.stp.StpUtil
import cn.dev33.satoken.util.SaResult
import io.github.frailty9.crserver.config.CrGlobalConfig
import io.github.frailty9.crserver.dso.service.AccountService
import io.github.frailty9.crserver.dto.RegisterDto
import io.github.frailty9.crserver.utils.toDto
import org.apache.ibatis.exceptions.PersistenceException
import org.noear.solon.annotation.Controller
import org.noear.solon.annotation.Inject
import org.noear.solon.annotation.Mapping
import org.noear.solon.annotation.Post
import org.noear.solon.web.cors.annotation.CrossOrigin
import java.sql.SQLIntegrityConstraintViolationException

@Suppress("unused")
@CrossOrigin(origins = "*")
@Controller
@Mapping("/api/account")
class AccountController {

    @Inject
    private lateinit var crGlobalConfig: CrGlobalConfig

    @Inject
    private lateinit var accountService: AccountService

    @Mapping("/unexist")
    fun unexist(username: String): SaResult {
        return if (accountService.isUsernameExists(username)) {
            SaResult.error("用户名已存在")
        } else {
            SaResult.ok()
        }
    }

    @Post
    @Mapping("/register")
    @SaCheckRole("sys_admin")
    fun register(registerDto: RegisterDto): SaResult {
        try {
            accountService.register(registerDto)
            return SaResult.ok()
        } catch (e: PersistenceException) {
            if (e.cause is SQLIntegrityConstraintViolationException)
            return SaResult.error("用户已存在") else throw e
        }
    }

    @Post
    @Mapping("/login")
    fun login(username: String, password: String): SaResult {
        val loginId = accountService.login(username, password)
        return if (loginId != 0L) {
            SaResult.data(StpUtil.getTokenInfo().toDto())
        } else {
            SaResult.error("用户名或密码错误")
        }
    }

    @Mapping("/password")
    fun password(oldPassword: String, newPassword: String): SaResult {
        val uid = StpUtil.getLoginIdAsLong()
        return if (accountService.changePassword(uid, oldPassword, newPassword)) {
            SaResult.ok()
        } else {
            SaResult.error("旧密码错误")
        }
    }

    @Mapping("/logout")
    fun logout(): SaResult {
        StpUtil.logout()
        return SaResult.ok()
    }

    @Mapping("/list")
    @SaCheckRole("sys_admin")
    fun list(): SaResult {
        val list = accountService.getAll()
        return SaResult.data(list)
    }

    @Mapping("/reset-pwd")
    @SaCheckRole("sys_admin")
    fun resetPwd(userId: Long): SaResult {
        val defaultPwd = crGlobalConfig.getDefaultHashedPwd()
        accountService.resetPassword(userId, defaultPwd)
        return SaResult.ok()
    }
}